/***
使用芯片stc12c2052ad,使外部晶振12MHz
音节选择由P1口实现
声音频率由定时器0产生PWM控制P37口实现（频率取值C大调，有改动）,定时器每次计数大约1us
更多说明可关注微信公众号：电子创客派（ID：e_diy_c）
***/
#include <stc12c2052ad.h>

#define u8 unsigned char
#define u16 unsigned short int

//音节对应的定时器值
u16 code TABLE[8] = {57888, 58736, 59476, 59908, 60436, 60992, 61488, 61712};

//开机歌曲
u16 code GEQU0[61] = {56448, 57888, 56448, 57888, 0, 56448, 57888, 56448, 57888, 0, 58736, 0, 55336, 57440, 55336, 57440, 0, 55336, 57440, 55336, 57440, 0, 57888, 56448, 57888, 59476, 58736, 57888, 59476,
										55336, 59908, 59476, 59908, 59476, 58736, 57888, 58736, 59476, 57888, 56448, 57888, 60436, 57888, 59476, 0, 59476,
										55336, 59908, 59476, 59908, 59476, 58736, 57888, 58736, 59476, 60992, 60436, 57440, 57888, 58736, 57888};
u16 code GEQU1[61] = {150, 150, 150, 300, 150, 150, 150, 150, 300, 300, 300, 150, 150, 150, 150, 300, 150, 150, 150, 150, 300, 300, 300, 300, 300, 300, 300, 300, 1000,
										300, 300, 900, 300, 600, 600, 600, 300, 600, 600, 600, 300, 600, 300, 300, 10, 900,
										300, 300, 900, 300, 600, 600, 600, 300, 600, 600, 600, 300, 600, 600, 900};

u8 Key = 0;								//音节按键值,独立按键由P1端口实现

u16 Times = 0;						//定时器0计数值
u8 R_TH0 = 0;							//定时器0重载计数值
u8 R_TL0 = 0;

void delay_ms(u16 n);

void main()
{
	P33 = 1;
	P34 = 0;
	P35 = 1;
	
	//设置P1为输入
	P1 = 0xff;
	
	//设置P37为推挽输出
	P3M1 = 0x80;
	P3M0 = 0x00;
	
	EX0 = 1;		//外部中断0打开
	IT0 = 1;		//外部中断0下降沿触发
	ET0 = 1;		//定时器0中断打开
	TR0 = 0;		//关闭定时器0计数
	EA = 1;			//中断总开关打开
	
	//播放开机歌曲
	if(1)
	{
		u8 i = 0;
		
		EX0 = 0;
		
		while(i < 61)
		{
			if(GEQU0[i] == 0)
				TR0 = 0;
			else
			{
				R_TH0 = (GEQU0[i] & 0xff00) >> 8;
				R_TL0 = GEQU0[i] & 0x00ff;
				TR0 = 1;
			}
			delay_ms(GEQU1[i]);
			i++;
		}
		
		TR0 = 0;
		EX0 = 1;
	}

	P31 = 1;
	
	while(1)
	{
		P37 = 0;
		if(P1 != 0x00)
		{
			delay_ms(10);
			if(P1 != 0x00)
			{
				u8 temp  = P1;
				u8 temp1  = temp;
				Key = 0;
				while(!(temp & 0x01))
				{
					temp = temp >> 1;
					Key++;
				}
				
				Times = TABLE[Key];
				R_TH0 = (Times & 0xff00) >> 8;
				R_TL0 = Times & 0x00ff;
				TL0 = R_TL0;
				TH0 = R_TH0;				
				TR0 = 1;		//打开定时器0计数
				
				while(P1 == temp1);
				TR0 = 0;		//关闭定时器0计数
			}
		}
	}
}

void delay1ms()		//@12.000MHz
{
	unsigned char i, j;

	i = 12;
	j = 169;
	do
	{
		while (--j);
	} while (--i);
}

void delay_ms(u16 n)
{
	while(n--) delay1ms();
}

//定时器中断0
void timer0() interrupt 1 using 1
{
	TL0 = R_TL0;
	TH0 = R_TH0;
	P37 = ~P37;
}